<script lang="ts">
	import { goto } from '$app/navigation';
	import { onMount } from 'svelte';
	import { page } from '$app/state';

	// 游戏状态类型定义
	type Tile = number; // 0 表示空白格子
	type GameState = {
		tiles: Tile[];
		moveCount: number;
		emptyIndex: number;
		showWinMessage: boolean;
	};

	// 初始化游戏状态
	let state: GameState = {
		tiles: [1, 2, 3, 4, 5, 6, 7, 8, 0],
		moveCount: 0,
		emptyIndex: 8,
		showWinMessage: false
	};

	// 初始化游戏
	onMount(() => {
		shuffleTiles();
	});

	// 渲染格子并处理点击
	function handleTileClick(index: number) {
		const adjacentIndexes = getAdjacentIndexes(state.emptyIndex);

		if (adjacentIndexes.includes(index)) {
			// 交换格子位置
			const newTiles = [...state.tiles];
			[newTiles[index], newTiles[state.emptyIndex]] = [newTiles[state.emptyIndex], newTiles[index]];

			// 更新状态
			state = {
				...state,
				tiles: newTiles,
				emptyIndex: index,
				moveCount: state.moveCount + 1
			};

			// 检查是否完成
			if (isPuzzleSolved()) {
				state = { ...state, showWinMessage: true };
			}
		}
	}

	// 获取空白格子的相邻位置
	function getAdjacentIndexes(emptyIndex: number): number[] {
		const adjacentIndexes: number[] = [];
		const row = Math.floor(emptyIndex / 3);
		const col = emptyIndex % 3;

		// 上
		if (row > 0) adjacentIndexes.push(emptyIndex - 3);
		// 下
		if (row < 2) adjacentIndexes.push(emptyIndex + 3);
		// 左
		if (col > 0) adjacentIndexes.push(emptyIndex - 1);
		// 右
		if (col < 2) adjacentIndexes.push(emptyIndex + 1);

		return adjacentIndexes;
	}

	// 检查谜题是否解决
	function isPuzzleSolved(): boolean {
		for (let i = 0; i < state.tiles.length - 1; i++) {
			if (state.tiles[i] !== i + 1) {
				return false;
			}
		}
		return true;
	}

	// 打乱格子
	function shuffleTiles() {
		let newTiles = [...state.tiles];

		// Fisher-Yates 洗牌算法
		for (let i = newTiles.length - 1; i > 0; i--) {
			const j = Math.floor(Math.random() * (i + 1));
			[newTiles[i], newTiles[j]] = [newTiles[j], newTiles[i]];
		}

		// 更新空白格子位置
		const newEmptyIndex = newTiles.indexOf(0);

		// 确保谜题可解
		if (!isSolvable(newTiles)) {
			// 如果不可解，交换两个非空白格子
			const nonEmptyIndices = newTiles
				.map((tile, index) => ({ tile, index }))
				.filter((item) => item.tile !== 0)
				.map((item) => item.index);

			[newTiles[nonEmptyIndices[0]], newTiles[nonEmptyIndices[1]]] = [
				newTiles[nonEmptyIndices[1]],
				newTiles[nonEmptyIndices[0]]
			];
		}

		// 重置游戏状态
		state = {
			tiles: newTiles,
			moveCount: 0,
			emptyIndex: newEmptyIndex,
			showWinMessage: false
		};
	}

	// 检查谜题是否可解
	function isSolvable(tiles: Tile[]): boolean {
		// 3x3 谜题可解的条件是逆序数为偶数
		let inversions = 0;
		const flattened = tiles.filter((tile) => tile !== 0);

		for (let i = 0; i < flattened.length; i++) {
			for (let j = i + 1; j < flattened.length; j++) {
				if (flattened[i] > flattened[j]) {
					inversions++;
				}
			}
		}

		return inversions % 2 === 0;
	}

	// 重新开始游戏
	function restartGame() {
		state = { ...state, showWinMessage: false };
		shuffleTiles();
	}
</script>

{#if page.status === 404}
	<div class="container">
		<h1 class="error-code">404</h1>
		<p class="error-message">哎呀！页面走丢了，但别担心，这里有个小游戏等你来玩</p>

		<div class="game-container">
			<!-- 游戏棋盘 -->
			<div class="game-board">
				{#each state.tiles as tile, index}
					<div
						class="tile {tile === 0 ? 'empty' : ''}"
						on:click={() => !state.showWinMessage && tile !== 0 && handleTileClick(index)}
						on:keydown={() => {}}
						id={tile !== 0 && getAdjacentIndexes(state.emptyIndex).includes(index)
							? `hint-${index}`
							: ''}
						role="button"
						aria-label={tile === 0 ? '空白位置' : `数字 ${tile}，可点击移动`}
						tabindex="0"
					>
						{tile !== 0 ? tile : ''}
					</div>
				{/each}
			</div>

			<div class="game-info">
				<h3>数字华容道</h3>
				<p>通过移动数字方块，按顺序从1到8排列它们。点击与空白相邻的数字方块可以移动它。</p>
				<div class="moves">移动步数: <span>{state.moveCount}</span></div>
				<div class="buttons">
					<button on:click={shuffleTiles} aria-label="重新开始游戏"> 重新开始 </button>
					<button on:click|preventDefault={() => goto('/home')} aria-label="返回首页">
						返回首页
					</button>
				</div>
			</div>
		</div>
	</div>

	<!-- 胜利提示 -->
	{#if state.showWinMessage}
		<div class="win-message">
			<div class="win-content">
				<h2>恭喜！</h2>
				<p>你成功完成了数字华容道！</p>
				<p>移动步数: <span>{state.moveCount}</span></p>
				<button on:click={restartGame} aria-label="再玩一次"> 再玩一次 </button>
			</div>
		</div>
	{/if}

	<style scoped lang="scss">
		.container {
			background: linear-gradient(
				135deg,
				var(--color-secondary-500) 0%,
				var(--color-primary-500) 100%
			);
			color: white;
			display: flex;
			flex-direction: column;
			align-items: center;
			justify-content: center;
			padding: 20px;
			text-align: center;
			height: 100vh;
		}

		.error-code {
			font-size: 120px;
			font-weight: 800;
			line-height: 1;
			margin-bottom: 10px;
			text-shadow: 3px 3px 0 rgba(0, 0, 0, 0.2);
			text-align: center;
		}

		.error-message {
			font-size: 24px;
			margin-bottom: 30px;
			opacity: 0.9;
			text-align: center;
		}

		.game-container {
			display: flex;
			flex-wrap: wrap;
			gap: 30px;
			justify-content: center;
			align-items: center;
			margin: 30px 0;
		}

		.game-board {
			width: 300px;
			height: 300px;
			display: grid;
			grid-template-columns: repeat(3, 1fr);
			grid-template-rows: repeat(3, 1fr);
			gap: 8px;
			background: rgba(255, 255, 255, 0.2);
			border-radius: 10px;
			padding: 10px;
			box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
		}

		.tile {
			background: white;
			border-radius: 8px;
			display: flex;
			align-items: center;
			justify-content: center;
			font-size: 32px;
			font-weight: bold;
			color: #333;
			cursor: pointer;
			transition: all 0.3s ease;
			box-shadow: 0 3px 5px rgba(0, 0, 0, 0.1);
		}

		.tile:hover:not(.empty) {
			transform: scale(1.05);
			box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
		}

		.empty {
			background: transparent;
			box-shadow: none;
			cursor: default;
		}

		.game-info {
			flex: 1;
			min-width: 250px;
			text-align: left;
			padding: 20px;
		}

		.game-info h3 {
			margin-bottom: 15px;
			font-size: 22px;
		}

		.game-info p {
			margin-bottom: 15px;
			line-height: 1.6;
			opacity: 0.9;
		}

		.moves {
			font-size: 18px;
			margin: 15px 0;
			font-weight: bold;
		}

		.buttons {
			display: flex;
			gap: 20px;
			justify-content: center;
			margin-top: 20px;
		}

		button {
			padding: 12px 25px;
			border: none;
			border-radius: 50px;
			background: white;
			color: var(--color-primary-500);
			font-size: 16px;
			font-weight: 600;
			cursor: pointer;
			transition: all 0.3s ease;
			box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
		}

		button:hover {
			transform: translateY(-3px);
			box-shadow: 0 8px 20px rgba(0, 0, 0, 0.2);
		}

		.win-message {
			position: fixed;
			top: 0;
			left: 0;
			width: 100%;
			height: 100%;
			background: rgba(0, 0, 0, 0.8);
			align-items: center;
			justify-content: center;
			z-index: 100;
			animation: fadeIn 0.5s;
			display: flex;
		}

		.win-content {
			background: white;
			color: #333;
			padding: 40px;
			border-radius: 20px;
			text-align: center;
			max-width: 500px;
			width: 90%;
			box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
			animation: scaleIn 0.5s;
		}
		.win-content p {
			font-size: 16px;
			padding: 5px;
		}
		.win-content h2 {
			font-size: 24px;
			color: var(--color-error-500);
			margin-bottom: 15px;
		}

		.win-content button {
			margin-top: 20px;
		}

		@keyframes fadeIn {
			from {
				opacity: 0;
			}
			to {
				opacity: 1;
			}
		}

		@keyframes scaleIn {
			from {
				transform: scale(0.8);
				opacity: 0;
			}
			to {
				transform: scale(1);
				opacity: 1;
			}
		}

		@media (max-width: 600px) {
			.error-code {
				font-size: 80px;
			}

			.game-container {
				flex-direction: column;
			}

			.game-board {
				width: 250px;
				height: 250px;
			}
		}
	</style>
{/if}
